/*
MIT License

Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,

https://bmstu.codes/lsx/simodo
*/

#include "simodo/utility/common_functions.h" 
#include "simodo/inout/convert/functions.h"
#include "simodo/inout/reporter/Reporter_abstract.h"

#include <iostream>
#include <fstream>

namespace simodo::utility
{

std::string getMnemonic(const inout::Lexeme &lex, bool abstract_lexeme)
{
    std::string mnemonic;

    switch(lex.type())
    {
    case inout::LexemeType::Empty:
        mnemonic = "$";
        break;
    case inout::LexemeType::Compound:
        mnemonic = inout::toU8(lex.lexeme());
//            mnemonic = "\\" + convertToU8(lex.lexeme());
        break;
    case inout::LexemeType::Punctuation:
        mnemonic = "'" + inout::toU8(lex.lexeme()) + "'";
        break;
    case inout::LexemeType::Id:
        mnemonic = abstract_lexeme ? "ID" : inout::toU8(lex.lexeme());
        break;
    case inout::LexemeType::Annotation:
        mnemonic = abstract_lexeme ? "ANNOTATION" : ("\"" + inout::toU8(lex.lexeme()) + "\"");
        break;
    case inout::LexemeType::Number:
        mnemonic = abstract_lexeme ? "NUMBER" : inout::toU8(lex.lexeme());
        break;
    case inout::LexemeType::Comment:
        mnemonic = "COMMENT";
        break;
    case inout::LexemeType::Error:
        mnemonic = "ERROR";
        break;
    default:
        mnemonic = "***";
        break;
    }

    return mnemonic;
}

namespace
{
    void shiftString(int level, int shift, std::string str)
    {
        for(int i=0; i < shift; ++i)
            std::cout << "\t";

        for(int i=0; i < level; ++i)
            std::cout << "\t";

        if (!str.empty())
            std::cout << str << std::endl;
    }
}

void printSemanticTree(const ast::Node & ast, const inout::uri_set_t & files, int level, int shift)
{
    shiftString(level, shift, "{");

    for(const ast::Node & n : ast.branches())
    {
        shiftString(level, shift, "");

        std::cout << "\t"
             << n.operation() << " \""
             << inout::toU8(n.token().lexeme()) << "\"";

        std::cout << "\t// " << getLocationString(n.bound().makeLocation(files),true) << std::endl;

        if (!n.branches().empty())
            printSemanticTree(n,files, level+1,shift);
    }

    shiftString(level, shift, "}");
}

void replaceAll(std::string &str, const std::string &from, const std::string &to)
{
    if(from.empty())
        return;

    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos)
    {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}

std::string toHtml(std::string text)
{
    replaceAll(text, "&", "&amp;");
    replaceAll(text, "<", "&lt;");
    replaceAll(text, ">", "&gt;");

    return text;
}

}